#include "serialport.h"
#include "tools/codeconvertor.h"
#include <QDataStream>
#include <QTextStream>
#include <QDebug>
#include <iostream>



SerialPort::SerialPort(QObject *parent, const QString &fileName, SerialPortMode mode) :
    QObject(parent),
    p_serialPort(NULL),
    m_currentSize(0x00),
    isRunning(false),
    m_fileName(fileName),
    workMode(mode),
    headFlag('X')
{
    // p_serialPort = new Posix_QextSerialPort(fileName,getPortSettings(workMode),QextSerialBase::Polling);
  //  m_timer.setInterval(50);
    // connect(&m_timer,SIGNAL(timeout()),this,SLOT(slt_parseSerialPortData()));
    m_test_timer.setSingleShot(true);
  //  connect(&m_timer,SIGNAL(timeout()),this,SLOT(slt_parse()));
    connect(&m_test_timer,SIGNAL(timeout()),this,SLOT(slt_showError()));
}
SerialPort::~SerialPort()
{
    this->close();
    delete p_serialPort;
}

//这个函数没有启动
void SerialPort::slt_parseSerialPortData()
{
    if (workMode == ZIGBEE) {
        if (m_currentSize == 0x00) {
            qDebug() << p_serialPort->readBufSize();
            if (p_serialPort->readBufSize()< (qint64)(2 * sizeof(char))) {
                return;
            } else {
                headFlag = static_cast<char>(this->readAquint8());
                if (headFlag != 'E' && headFlag != 'R' && headFlag != 'C') {
                    return;
                } else {
                    m_currentSize = this->readAquint8() - '0';

                }
            }
        } else {
            qDebug() << p_serialPort->readBufSize();
            if (p_serialPort->readBufSize() < m_currentSize - 2) {
                return;
            } else {
                SerialPortData sdata;
                sdata.cmd = readAquint8();
                qint64 datalen = static_cast<qint64>(m_currentSize - 1);
                sdata.data = p_serialPort->read(datalen);
                sdata.type = headFlag;
                if (sdata.data.length() == datalen) {
                    emit sig_SerialPortDataComed(sdata);
                }
                m_currentSize = 0x00;
            }
        }
    } else {
        //Mode is GSM,operators here | not operators


    }





}
void SerialPort::slt_parse()
{
    if (!isRunning) {
        return;
    }
    m_buffer.append(p_serialPort->readAll());
#ifndef NEW_DATA_STYLE

    while (true) {
        if (m_buffer.isEmpty()) {
            break;
        }
        if (workMode == ZIGBEE) {
            if (m_currentSize != 0x00) {
                if (m_buffer.length() >= m_currentSize - 2) {
                    SerialPortData sdata;
                    sdata.cmd = m_buffer.at(0);
                    sdata.data = m_buffer.mid(1,m_currentSize - 3);
                    m_buffer.remove(0,m_currentSize);
                    sdata.type = headFlag;
                    emit sig_SerialPortDataComed(sdata);
                    m_currentSize = 0x00;
                    headFlag = 'X';

                    qDebug() <<sdata.type <<sdata.cmd << sdata.data;
                }
                break;

            }
            if (headFlag != 'X') {
                m_currentSize = static_cast<quint8> (m_buffer.at(0)) - '0';
                m_buffer.remove(0,1);
                continue;
            }

            char t = m_buffer.at(0);
            m_buffer.remove(0,1);
            if (t != 'E' && t != 'R' && t != 'C') {
                continue;
            } else {
                headFlag = t;
            }

        } else {//GSM
            QString str = help_gsm_read("CMTI");
            if (!str.isEmpty()) {
                QString re = help_gsm_read(str);
                emit new_gsmMessage(parsePhoneGSM(re));
                m_buffer.clear();
            }



        }
    }


    QTimer::singleShot(0,this,SLOT(slt_parse()));
#else
    while(true) {
        if (m_buffer.isEmpty()) {
            break;
        }
        if (m_buffer.length() > 16) {
            if (m_buffer[0] == 0xFF
                    && m_buffer[1] == 0x00
                    && m_buffer[2] == 0xFF
                    && m_buffer[3] == 0x00 ) {
                if (m_buffer[5] == 0x10) {
                    continue;
                } else {
                    SerialPortData sdata;
                    sdata.cmd = SENSOR;
                    sdata.data = m_buffer.mid(4,9);
                    m_buffer.remove(0,16);
                    sdata.type = m_buffer[4];
                    emit sig_SerialPortDataComed(sdata);
                }
            } else {
                while(true) {
                    m_buffer.remove(0,1);
                    if (m_buffer.at(0) == 0xFF) break;
                }
            }
        } else {
            break;
        }


    }
#endif


}

void SerialPort::sendAcmd(unsigned char cmd)
{
    char buff[2];
    buff[0] = cmd;
    buff[1] = '\0';
    p_serialPort->write(buff);
    p_serialPort->flush();
}
PortSettings SerialPort::getPortSettings(SerialPortMode mode)
{
    QFile file;
    if (mode == ZIGBEE) {
        file.setFileName("conf/serialPort.conf");
    } else {
        //....
        file.setFileName("conf/GSM.conf");
    }

    if (!file.open(QIODevice::ReadOnly)) {
        return PortSettings();
    }
    QTextStream stream(&file);
    QString baudRate = stream.readLine();
    QString dataBits = stream.readLine();
    QString parity = stream.readLine();
    QString stopBits = stream.readLine();
    QString timeOut = stream.readLine();
    QString flowType = stream.readLine();
    file.close();

    PortSettings settings;

    setBaudRate(settings,baudRate);
    setDataBits(settings,dataBits);
    setParity(settings,parity);
    setstopBits(settings,stopBits);
    setTimeOut(settings,timeOut);
    setFlowType(settings,flowType);

    return settings;

}
void SerialPort::setBaudRate(PortSettings &settings, const QString &baudRate)
{
    if (baudRate == "115200") {
        settings.BaudRate = BAUD115200;
    } else {
        if (baudRate == "9600") {
            settings.BaudRate = BAUD9600;
        } else {
            if (baudRate == "57600") {
                settings.BaudRate = BAUD57600;
            }

        }
    }
}

void SerialPort::setDataBits(PortSettings &settings, const QString &dataBits)
{
    if (dataBits == "8") {
        settings.DataBits = DATA_8;
    } else if(dataBits == "7") {
        settings.DataBits = DATA_7;
    } else  {


    }
}

void SerialPort::setParity(PortSettings &settings, const QString &parity)
{
    if (parity == "0") {
        settings.Parity = PAR_NONE;
    } else {
        if (parity == "1") {
            settings.Parity = PAR_ODD;
        } else {
            settings.Parity = PAR_EVEN;
        }
    }
}
void SerialPort::setstopBits(PortSettings &settings, const QString &stopBits)
{
    if (stopBits == "1") {
        settings.StopBits = STOP_1;
    } else {
        if (stopBits == "1.5") {
            settings.StopBits = STOP_1_5;
        } else {
            settings.StopBits = STOP_2;
        }
    }
}
void SerialPort::setTimeOut(PortSettings &settings, const QString &ms)
{
    int t = ms.toLong();
    settings.Timeout_Millisec = t;
}
void SerialPort::setFlowType(PortSettings &settings, const QString &flowtype)
{
    int i = flowtype.toInt();
    settings.FlowControl = (FlowType)(i);
}
quint8 SerialPort::readAquint8()
{
    char buff[2];
    if (p_serialPort->read(buff,1) != 1) {
        return static_cast<quint8>(0);
    }
    buff[1] = '\0';
    return static_cast<quint8>(buff[0]);

}
void SerialPort::reset()
{
    const PortSettings &settings = getPortSettings(workMode);
    p_serialPort->setBaudRate(settings.BaudRate);
    p_serialPort->setDataBits(settings.DataBits);
    p_serialPort->setParity(settings.Parity);
    p_serialPort->setFlowControl(settings.FlowControl);
    p_serialPort->setStopBits(settings.StopBits);
}
void SerialPort::Open()
{
    if (p_serialPort == NULL) {
        p_serialPort = new Posix_QextSerialPort(m_fileName,getPortSettings(workMode),QextSerialBase::Polling);
    }
    if (p_serialPort->isOpen()) {
    } else {
        if (p_serialPort->open(QIODevice::ReadWrite)) {


            if (GSM == workMode) {
                startByGSM();
            } else {
                test_coor();
                // if (test_coor()) {
                // m_timer.start();

                // emit sig_realTimeInfo(trUtf8("ZigBee-->网络接入串口打开成功！"));
                // emit sig_SerialPortInfo(m_fileName,true);
                // } else {
                // emit sig_realTimeInfo(trUtf8("ZigBee-->网络接入串口打开失败！"));
                // emit sig_SerialPortInfo(m_fileName,false);
                // }

            }



        } else {
            emit sig_SerialPortInfo(m_fileName,false);

            if (workMode == GSM) {
                emit sig_realTimeInfo(trUtf8("GSM-->网络接入串口打开失败！"));

            } else {
                emit sig_realTimeInfo(trUtf8("ZigBee-->网络接入串口打开失败！"));
            }
        }

    }

}
void SerialPort::close()
{
    if (p_serialPort == NULL) return;
    if (p_serialPort->isOpen()) {
        //m_timer.stop();
        isRunning = false;
        p_serialPort->flush();
        p_serialPort->close();
        /**
          缓冲去清零
          */
        m_buffer.clear();

        emit sig_close();

        if (workMode == GSM) {
            emit sig_realTimeInfo(trUtf8("GSM-->gsm串口已经关闭！"));
        } else {
            emit sig_realTimeInfo(trUtf8("ZigBee-->zigbee串口已经关闭！"));
        }

    }

}
void SerialPort::slt_open(const QString &file, SerialPortMode mode)
{
    if (file == m_fileName) {
        if (p_serialPort == NULL) {
            this->changeWorkMode(mode);
            this->Open();
        } else {
            if (workMode == mode) {
                this->Open();
            } else {
                this->close();
                this->changeWorkMode(mode);
                this->Open();
            }

        }
        return;
    }
    if (p_serialPort != NULL) {
        this->close();
        delete p_serialPort;
    }
    p_serialPort = new Posix_QextSerialPort(file,getPortSettings(mode),QextSerialBase::Polling);
    m_fileName = file;
    workMode = mode;
    this->Open();
}
void SerialPort::changeCollectTimer(int ms)
{
    Q_UNUSED(ms);
    //m_timer.stop();
    //m_timer.start(ms);
}
void SerialPort::changeWorkMode(SerialPortMode mode)
{
    workMode = mode;
}

void SerialPort::slt_writeSerialPort(const char *value)
{
    p_serialPort->write(value);
    p_serialPort->flush();
}

void SerialPort::slt_writeSerialPort(const QByteArray &data)
{
#ifndef TEST_NET
    p_serialPort->write(data);
    p_serialPort->flush();
#else
    Q_UNUSED(data);
#endif
}

void SerialPort::slt_SerialPortInfo(const QString &fileName)
{
    if (m_fileName == fileName) {
        if (p_serialPort == NULL) {
            emit sig_SerialPortInfo(fileName,false);
        } else {
            emit sig_SerialPortInfo(fileName,p_serialPort->isOpen());
        }

    } else {

        emit sig_SerialPortInfo(fileName,false);
    }

}

void SerialPort::slt_setDevOnOrOff(const QString &fileName, bool onOff)
{
    if (fileName == m_fileName) {
        if (onOff) {
            this->Open();
        } else {
            this->close();
            emit sig_SerialPortInfo(m_fileName,false);
        }
    } else {
        this->slt_open(fileName,workMode);
    }

}
/**
 * @brief SerialPort::startByGSM
 *
 *
 *
 */
void SerialPort::startByGSM()
{
    p_serialPort->write("AT\r");
    p_serialPort->flush();
    Sleep::Zsleep(1);
    QByteArray c = p_serialPort->readAll();
    if (c.contains("OK")) {
        c.clear();
        p_serialPort->write("AT+CNMI=2,1,0,0,1\r");
        p_serialPort->flush();
        Sleep::Zsleep(1);
        c = p_serialPort->readAll();
        if (c.contains("OK")) {
            emit sig_GSMCMDok(AT_OK);
            emit sig_SerialPortInfo(m_fileName,true);
            //m_timer.start();
            isRunning = true;
            QTimer::singleShot(TIMEOUT(5),this,SLOT(slt_parse()));
        }
    }
    else {
        emit sig_GSMCMDok(AT_ERROR);
    }


}

void SerialPort::slt_AT_CMGF()
{
    p_serialPort->write("AT+CMGF=0\r");
    p_serialPort->flush();
    Sleep::Zsleep(1);
    QByteArray c = p_serialPort->readAll();
    if (c.contains("OK")) {
        emit sig_GSMCMDok(AT_CMGF_OK);
    }
    else {
        emit sig_GSMCMDok(AT_CMGF_ER);
    }

}/**
 * @brief SerialPort::slt_AT_CMGS
 *
 *
 * @param len 信息长度
 */
void SerialPort::slt_AT_CMGS(int len)//发送短信的长度
{
    p_serialPort->write(tr("AT+CMGS=%1\r").arg(len).toLatin1().data());
    p_serialPort->flush();
    Sleep::Zsleep(1);
    QByteArray c = p_serialPort->readAll();
    if (c.contains(">")) {
        emit sig_GSMCMDok(AT_CMGS_OK);
    }
    else {
        emit sig_GSMCMDok(AT_CMGS_ER);
    }

}
/**
 * @brief SerialPort::slt_AT_Content
 * 向串口写信息的编码后的内容
 * @param content 内容
 */
void SerialPort::slt_AT_Content(const QByteArray &content)
{
    QByteArray t(content);
    t.append(0x1A);
    p_serialPort->write(t);
    p_serialPort->flush();
    Sleep::Zsleep(2);
    QByteArray c = p_serialPort->readAll();
    if (c.contains("ERROR")) {
        emit sig_GSMCMDok(AT_SEND_ER);
    } else {
        emit sig_GSMCMDok(AT_SEND_OK);
    }


}

void SerialPort::slt_close()
{
    this->close();
}


//不会使用
void SerialPort::slt_AT_CNMI()
{
    p_serialPort->write("AT+CNMI=2,1,0,0,0\r");
    p_serialPort->flush();
    Sleep::Zsleep(1);
    QByteArray c = p_serialPort->readAll();
    if (c.contains("OK")) {
        emit sig_GSMCMDok(AT_CMGF_OK);
    }
    else {
        emit sig_GSMCMDok(AT_CMGF_ER);
    }

}

QString SerialPort::help_gsm_read(const QString &flag)
{
    QString re;
    if (flag == "CMTI") {
        if (m_buffer.mid(3,4) == flag) {
            re = m_buffer.mid(14,1);
        }
    } else {//CMGR
        //截取有效的数据返回供解析
        QString a = trUtf8("AT+CMGR=%1\r").arg(flag);
        p_serialPort->write(a.toLatin1());
        p_serialPort->flush();//
        Sleep::sleep(1);
        re = p_serialPort->readAll();
        re = re.split('\n').at(2);
        re.remove(re.length()-1,1);
        //写入控制数据
        //接受数据

    }
    return re;
}


//这个是为了测试协调器节点是否正常工作
//这是一个一步操作
void SerialPort::test_coor()
{
    //  bool re = false;
    QByteArray barr = QString("FFFF%1").arg(COORDINATOR_TEST).toLatin1();
    emit sig_realTimeInfo(trUtf8("ZigBee-->正在测试，请耐心等待！"));
    wirteCMD(barr);
    m_test_timer.start(25 * 1000 * 2);//这个和协调器的处理时间匹配，最少大于。
}


//需要完成的函数，解析函数,使用的功能函数在CodeConvertor类中寻找

//0891683108500145F1240D91685143256178F0000831218201304123064F6059B9554A
GSMCommand SerialPort::parsePhoneGSM(const QString &instr)
{


    QString phone = CodeConvertor::phone_frame(instr.mid(26,12));
    QString time = CodeConvertor::date_time_frame(instr.mid(42,12));
    QString con = CodeConvertor::unicodeToUtf8(instr.mid(58));

    Args args;

    QStringList sl = con.split('#');

    flag_args a;
    for (int i = 0;i < sl.length() - 1;++i) {
        a.first = sl.at(i).toInt();
        a.second = sl.at(++i);
        args.append(a);
    }
    return GSMCommand(phone,args,time);
}

void SerialPort::slt_showError()
{

    emit sig_realTimeInfo(trUtf8("ZigBee-->网络接入串口打开失败！"));
    emit sig_SerialPortInfo(m_fileName,false);

}

void SerialPort::slt_stop_test_timer()
{
    m_test_timer.stop();
    emit sig_realTimeInfo(trUtf8("ZigBee-->网络接入串口打开成功！"));
    emit sig_SerialPortInfo(m_fileName,true);
    // m_timer.start();
    isRunning = true;
    QTimer::singleShot(TIMEOUT(5),this,SLOT(slt_parse()));
}

//写入命令数据
void SerialPort::wirteCMD(const QByteArray &arr)//xxxxx
{
    for (int i = 0;i < 5;++i) {
        char t[2];
        t[0] = arr.at(i);
        t[1] = '\0';
        p_serialPort->write(t);
        p_serialPort->flush();
        Sleep::Zsleep(3);
    }
}


